/*
 * acooly.cn Inc.
 * Copyright (c) 2016 All Rights Reserved.
 * create by zhangpu 
 * date:2016年4月4日
 *
 */
package com.acooly.module.openapi.client.provider.webank.marshall;

import com.google.common.collect.Maps;

import com.acooly.core.utils.Reflections;
import com.acooly.core.utils.Strings;
import com.acooly.core.utils.validate.Validators;
import com.acooly.module.openapi.client.api.exception.ApiClientException;
import com.acooly.module.openapi.client.provider.webank.WeBankProperties;
import com.acooly.module.openapi.client.provider.webank.domain.WeBankApiMessage;
import com.acooly.module.openapi.client.provider.webank.domain.WeBankRequest;
import com.acooly.module.openapi.client.provider.webank.partner.WeBankKeyPairManager;
import com.acooly.module.openapi.client.provider.webank.utils.MapHelper;
import com.acooly.module.openapi.client.provider.webank.utils.SignUtils;
import com.acooly.module.safety.Safes;
import com.acooly.module.safety.signature.SignTypeEnum;
import com.acooly.module.safety.signature.SignerFactory;

import org.springframework.beans.factory.annotation.Autowired;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import lombok.extern.slf4j.Slf4j;

/**
 * @author zhangpu
 */
@Slf4j
public class WeBankMarshallSupport {

    @Autowired
    protected WeBankProperties weBankProperties;

    @Autowired
    protected SignerFactory signerFactory;

    @Resource(name = "weBankGetKeyPairManager")
    private WeBankKeyPairManager keyPairManager;

    protected WeBankProperties getProperties() {
        return weBankProperties;
    }

    protected String doMarshall(WeBankRequest source) {
        doVerifyParam(source);
        Map<String, String> requestDataMap = getRequestDataMap(source);
        String signContent = SignUtils.getSignContent(requestDataMap);
        log.debug("待签字符串:{}", signContent);
        String signStr = doSign(signContent,requestDataMap.get("merId"));
        source.setSign(SignUtils.urlEncode(signStr));
        return signContent+"&signature="+source.getSign();
    }

    /**
     * 获取代签map
     *
     * @param source
     * @return
     */
    protected Map<String, String> getRequestDataMap(WeBankRequest source) {
        Map<String, String> requestData = Maps.newTreeMap();
        Set<Field> fields = Reflections.getFields(source.getClass());
        Object value = null;
        for (Field field : fields) {
            value = Reflections.getFieldValue(source, field.getName());
            if (value == null) {
                continue;
            }
            if (field.getType() != String.class) {
                requestData = MapHelper.toLinkedHashMap(value);
            }
        }
        return requestData;
    }

    /**
     * 验签
     *
     * @param signature
     * @param plain
     * @return
     */
    protected void doVerifySign(String signature, String plain, String partnerId) {
        Safes.getSigner(SignTypeEnum.Rsa.name ()).verify(plain, keyPairManager.getKeyPair(partnerId), signature);
    }


    /**
     * 校验参数
     *
     * @param source
     */
    protected void doVerifyParam(WeBankApiMessage source) {
        try {
            source.doCheck();
            Validators.assertJSR303(source);
        } catch (Exception e) {
            throw new ApiClientException(e.getMessage());
        }
    }


    protected void beforeMarshall(WeBankApiMessage message) {
        if(Strings.isBlank(message.getPartnerId())) {
            message.setPartnerId(getProperties().getPartnerId());
        }
    }


    protected String doSign(String waitForSign,String partnerId) {
        return Safes.getSigner(SignTypeEnum.Rsa.name()).sign(waitForSign, keyPairManager.getKeyPair(partnerId));
    }
}
